#include "common/logger/logger.h"


#include <controls/tree/cxitreenode.h>
#include <private/tree/cxitreenode_p.hpp>
CxiTreeNode::CxiTreeNode(Ptr parent)
{
	if (!parent)
	{
		LOG_WARN("CxiTreeNode::CxiTreeNode() - parent node is null");
		return;
	}
	m_pImplNode = std::make_unique<CxiTreeNodePrivate>(parent);
}
CxiTreeNode::~CxiTreeNode()
{
}

void CxiTreeNode::appendChild(Ptr child)
{
	if (!m_pImplNode)
	{
		LOG_WARN("CxiTreeNode::appendChild() - current node is null");
		return;
	}
	if (!child->m_pImplNode)
	{
		LOG_WARN("CxiTreeNode::appendChild() - child node is null");
	}

	auto self = shared_from_this();
	child->m_pImplNode->parent = self;
	m_pImplNode->children.push_back(child);
}

void CxiTreeNode::insertChild(int row, Ptr child)
{
	if (!m_pImplNode)
	{
		LOG_WARN("CxiTreeNode::insertChild() - current node is null");
		return;
	}
	if (!child->m_pImplNode)
	{
		LOG_WARN("CxiTreeNode::insertChild() - child node is null");
	}

	if (row >= 0 && row < m_pImplNode->children.size())
	{
		auto self = shared_from_this();
		child->m_pImplNode->parent = self;
		m_pImplNode->children.insert(m_pImplNode->children.begin() + row, child);
	}
}

void CxiTreeNode::removeChild(int row)
{
	auto self = shared_from_this();
	if (row >= 0 && row < m_pImplNode->children.size())
	{
		auto child = m_pImplNode->children[row];
		child->m_pImplNode->parent.reset();
		m_pImplNode->children.erase(m_pImplNode->children.begin() + row);
		return;
	}
	LOG_WARN("CxiTreeNode::removeChild() - row out of range");
}

CxiTreeNode::Ptr CxiTreeNode::child(int row)
{
	auto self = shared_from_this();
	if (row >= 0 && row < m_pImplNode->children.size())
	{
		return m_pImplNode->children[row];
	}
	return nullptr;
}
CxiTreeNode::Ptr CxiTreeNode::getChild(const QString& key, const QString& text)
{
	// 通过该树的两个索引哈希表进行查询，提升效率，O(N) -> O(1)
	auto root = shared_from_this();
	while (root->parent())
	{
		root = root->parent();// 找到根节点
	}

	auto& p = root->m_pImplNode;

	// 判断该树是否已经建立过索引哈希表
	if (!p->indexBuilt)
	{
		p->buildIndex(root);
		p->indexBuilt = true;
	}


	// 从 keyIndex 找候选节点
	auto it = p->keyIndex.find(key);
	if (it != p->keyIndex.end())
	{
		// 遍历候选节点，匹配 text
		for (auto& node: it.value())
		{
			if (node->text() == text)
			{
				return node;
			}
		}
	}

	// 未找到
	return nullptr;
}
CxiTreeNode::Ptr CxiTreeNode::getChildByKey(const QString& key)
{
	return this->getChildrenByKey(key).front();
}
std::vector<CxiTreeNode::Ptr> CxiTreeNode::getChildrenByKey(const QString& key)
{
	auto root = shared_from_this();
	while (root->parent()) root = root->parent();// 找到根节点

	auto& p = root->m_pImplNode;
	if (!p->indexBuilt)
	{
		p->buildIndex(root);
		p->indexBuilt = true;
	}

	auto it = p->textIndex.find(key);
	return (it != p->textIndex.end()) ? it.value() : std::vector<Ptr>{};
}
CxiTreeNode::Ptr CxiTreeNode::getChildByText(const QString& text)
{
	return this->getChildrenByKey(text).front();
}
std::vector<CxiTreeNode::Ptr> CxiTreeNode::getChildrenByText(const QString& text)
{
	auto root = shared_from_this();
	while (root->parent()) root = root->parent();// 找到根节点

	auto& p = root->m_pImplNode;
	if (!p->indexBuilt)
	{
		p->buildIndex(root);
		p->indexBuilt = true;
	}

	auto it = p->textIndex.find(text);
	return (it != p->textIndex.end()) ? it.value() : std::vector<Ptr>{};
}

int CxiTreeNode::childCount() const
{
	return this->m_pImplNode->children.size();
}
// int CxiTreeNode::row() const
// {
// 	return m_pImplNode->children.size();
// }
CxiTreeNode::Ptr CxiTreeNode::parent() const
{
	if (auto p = m_pImplNode->parent.lock())
		return p;
	else
		return nullptr;// 父节点不存在或已销毁
}
QString CxiTreeNode::key() const
{
	return m_pImplNode->key;
}
void CxiTreeNode::setKey(const QString& k)
{
	m_pImplNode->key = k;
}

QString CxiTreeNode::text() const
{
	return m_pImplNode->text;
}
void CxiTreeNode::setText(const QString& t)
{
	m_pImplNode->text = t;
}
QString CxiTreeNode::tooltip() const
{
	return m_pImplNode->tooltip;
}
void CxiTreeNode::setTooltip(const QString& t)
{
	m_pImplNode->tooltip = t;
}
bool CxiTreeNode::isEditable() const
{
	return m_pImplNode->editable;
}
void CxiTreeNode::setEditable(bool e)
{
	m_pImplNode->editable = e;
}
bool CxiTreeNode::checkable() const
{
	return m_pImplNode->checkable;
}
void CxiTreeNode::setCheckable(bool c)
{
	m_pImplNode->checkable = c;
}
Qt::CheckState CxiTreeNode::checkState() const
{
	return m_pImplNode->checkState;
}
void CxiTreeNode::setCheckState(Qt::CheckState s)
{
	m_pImplNode->checkState = s;
}
bool CxiTreeNode::showInCombo() const
{
	return m_pImplNode->showInCombo;
}
void CxiTreeNode::setShowInCombo(bool v)
{
	m_pImplNode->showInCombo = v;
}
QVariant CxiTreeNode::value() const
{
	return m_pImplNode->value;
}
void CxiTreeNode::setValue(const QVariant& v)
{
	m_pImplNode->value = v;
}
int CxiTreeNode::row()
{
	return m_pImplNode->parent.lock()->m_pImplNode->children.indexOf(shared_from_this());
}